/*
 * @Author: 吴世扬
 * @Date: 2022-09-10 17:43:55
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2025-09-19 10:59:08
 * @FilePath: /vue3-admin/src/store/modules/permission.ts
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import { ref } from 'vue';
import type {
    MenuTreeItem,
    MenuTreeWithMetaItem
} from '@/typings/store/permission';
import { defineStore } from 'pinia';
import router, { constantRoutes, resetRouter, authRoutes } from '@/router';
import { treeToArray, arrayToTree, type ListDataWithParent } from '@/utils';
import { useUserStore } from './user';
import { useAppStore } from './app';
import type { RouteRecordRaw } from 'vue-router';
import { store } from '@/store';

export const Layout = () => import('@/layout/Layout.vue');

export const findFromTree = <T extends { children?: T[] }>(
    menuTree: T[],
    fn: (item: T) => boolean
): T | undefined => {
    for (let i = 0; i < menuTree.length; i++) {
        const item = menuTree[i];
        if (fn(item)) {
            return item;
        } else {
            if (item.children) {
                const res = findFromTree(item.children, fn);
                if (res) {
                    return res;
                }
            }
        }
    }
};

export const filterAsyncRoutes = (
    menuTree: MenuTreeItem[],
    routes: AppRouteRecordRaw[]
) => {
    const flatArr = treeToArray<MenuTreeItem>(
        undefined,
        JSON.parse(JSON.stringify(menuTree))
    );
    const routeFlatArr = treeToArray<AppRouteRecordRaw>('name', routes);
    const menuTreeWithMeta: MenuTreeWithMetaItem[] = [];
    flatArr.forEach((menu) => {
        const route = routeFlatArr.find((it) => {
            return it.path === menu.path;
        });
        // 处理路由列表
        if (route) {
            route.meta.title = menu.name;
            menuTreeWithMeta.push(
                Object.assign(menu, {
                    meta: {
                        ...route.meta,
                        icon: menu.icon ?? route.meta.icon ?? 'user'
                    }
                })
            );
        } else {
            menuTreeWithMeta.push(
                Object.assign(menu, {
                    meta: {
                        name: menu.name,
                        title: menu.name,
                        path: '',
                        fullPath: '',
                        icon: menu.icon ?? 'user'
                    }
                })
            );
        }
    });
    return {
        menus: arrayToTree<MenuTreeWithMetaItem>(
            undefined,
            menuTreeWithMeta
        ) as MenuTreeWithMetaItem[],
        routes: arrayToTree<AppRouteRecordRaw>(
            'name',
            routeFlatArr
        ) as AppRouteRecordRaw[]
    };
};

export const usePermissionStore = defineStore('permission', () => {
    const userStore = useUserStore();
    const appStore = useAppStore();
    const routes = ref<RouteRecordRaw[]>([]); // 所有的路由
    const menus = ref<MenuTreeWithMetaItem[]>([]); // 所有的菜单
    const addRoutes = ref<RouteRecordRaw[]>([]); // 添加的路由
    const authPaths = computed(() => {
        const paths = treeToArray(undefined, menus.value)
            .map((menu) => menu.path)
            .filter((path) => path !== undefined);
        return paths;
    });
    const redirectPaths = computed(() => {
        const paths: string[] = [];
        treeToArray(undefined, routes.value).forEach((route) => {
            if (route.redirect) {
                paths.push(route.path);
            }
        });
        return paths;
    });

    const needUpdate = ref(true);

    const setRoutes = (data: AppRouteRecordRaw[]) => {
        routes.value = [...data, ...constantRoutes] as RouteRecordRaw[];
        addRoutes.value = data as RouteRecordRaw[];
    };

    const generateRoutes = () => {
        if (!userStore.menuTree)
            return console.error('userStore.menuTree不能为空');
        const { routes: filterRoutes, menus: filterMenus } = filterAsyncRoutes(
            userStore.menuTree,
            [...constantRoutes, ...authRoutes]
        );
        menus.value = filterMenus;
        setMixLeftMenus(appStore.activeIds); // 修改左侧菜单
        setRoutes(filterRoutes);
    };

    const updateRoutes = () => {
        routes.value = [];
        addRoutes.value = [];

        generateRoutes();
        // 重置路由,只保留白名单的路由
        resetRouter();
        console.log('before add', router.getRoutes());
        routes.value.forEach((route: RouteRecordRaw) => {
            if (route.path.indexOf('/') === 0) {
                router.addRoute(route as RouteRecordRaw);
            }
        });
        console.log('after add', router.getRoutes());
        return Promise.resolve(routes);
    };

    /**
     * 获取与激活的顶部菜单项相关的混合模式左侧菜单集合
     */
    const mixLeftMenus = ref<MenuTreeWithMetaItem[]>([]);
    const setMixLeftMenus = (activeIds: string) => {
        const arr = activeIds.split(',');
        const matchedItem = menus.value.find((item) => item.id === +arr[0]);
        if (matchedItem && matchedItem.children) {
            mixLeftMenus.value = matchedItem.children;
        }
        const menuList: ListDataWithParent<MenuTreeWithMetaItem>[] =
            treeToArray(undefined, menus.value);
        const current = arr.pop();
        const matchedCurrentItem = menuList.find(
            (item) => item.id === Number(current)
        );
        if (matchedCurrentItem && matchedCurrentItem.meta?.title) {
            document.title = matchedCurrentItem.meta?.title;
        }
    };

    /**
     * 通过路径获取关联菜单
     */
    const findRelatedNodes = (findPath: string) => {
        const flatArr = treeToArray<MenuTreeWithMetaItem>(
            undefined,
            menus.value
        );
        const node = flatArr.find((item) => item.path === findPath);
        const nodes: ListDataWithParent<MenuTreeWithMetaItem>[] = [];
        const findParent = (
            node: ListDataWithParent<MenuTreeWithMetaItem>
        ): MenuTreeWithMetaItem => {
            nodes.unshift(node);
            if (node.parentId) {
                const parent = flatArr.find(
                    (item) => item.id === node.parentId
                );
                if (parent === undefined) {
                    throw new Error('菜单数据异常');
                }
                return findParent(parent);
            }
            return node;
        };
        if (node) {
            findParent(node);
        }
        return nodes;
    };

    const findNodeById = (id: number) => {
        const flatArr = treeToArray<MenuTreeWithMetaItem>(
            undefined,
            menus.value
        );
        const target = flatArr.find((item) => item.id === id);
        return target || null;
    };

    const hasRouteAuth = (current: string) => {
        const constantPaths = treeToArray(undefined, constantRoutes).map(
            (route) => route.path
        );
        if (
            [...authPaths.value, ...redirectPaths.value, ...constantPaths].some(
                (path) => current === path
            )
        )
            return true;
        return false;
    };

    return {
        routes,
        menus,
        addRoutes,
        needUpdate,
        generateRoutes,
        updateRoutes,
        mixLeftMenus,
        setMixLeftMenus,
        findRelatedNodes,
        findNodeById,
        authPaths,
        redirectPaths,
        hasRouteAuth
    };
});

// 非setup
export function usePermissionStoreHook() {
    return usePermissionStore(store);
}
